package net.sudot.chess.plugin.payment;

import net.sudot.chess.business.model.PaymentTransaction;
import net.sudot.chess.business.model.PluginConfig;
import net.sudot.chess.plugin.BasePlugin;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 支付插件
 * <h2>支付跳转流程</h2>
 * <ol>
 * <li>
 * 提交支付请求
 * <p>在此请求里生成支付订单并调用支付前处理</p>
 * </li>
 * <li>支付前处理
 * <p>此请求主要处理用户身份认证并返回支付前处理视图从而发起支付处理</p>
 * </li>
 * <li>支付前处理视图
 * <p>主要处理用户身份认证,并发起实际支付处理</p>
 * </li>
 * <li>支付处理
 * <p>主要用于生成调用第三方支付接口的参数信息,并返回到支付处理视图发起第三方支付接口调用</p>
 * </li>
 * <li>支付处理视图
 * <p>发起第三方支付接口调用</p>
 * </li>
 * <li>支付后处理
 * <p>一般用于验证支付结果并跳转到支付结果视图</p>
 * </li>
 * <li>支付后结果视图
 * <p>用于展示支付结果,若为检测到支付结果,则在此视图重复发起支付结果检测请求</p>
 * </li>
 * <li>检查支付结果
 * <p>此接口主要用于第三方支付系统延迟返回支付结果信息时主动查询使用</p>
 * </li>
 * </ol>
 *
 * @author tangjialin on 2018-03-18.
 */
public abstract class PaymentPlugin extends BasePlugin {

    /** "LOGO"属性名称 */
    public static final String LOGO_ATTRIBUTE_NAME = "logo";

    /** "描述"属性名称 */
    public static final String DESCRIPTION_ATTRIBUTE_NAME = "description";

    /** 默认超时时间 */
    public static final Integer DEFAULT_TIMEOUT = 24 * 60 * 60;

    /** 默认支付视图名称 */
    public static final String DEFAULT_PAY_VIEW_NAME = "/payment/pay";

    /** 默认支付结果视图名称 */
    public static final String DEFAULT_PAY_RESULT_VIEW_NAME = "/payment/pay-result";

    /**
     * 获取LOGO
     *
     * @return LOGO
     */
    public String getLogo() {
        PluginConfig pluginConfig = getConfig();
        return pluginConfig == null ? null : pluginConfig.getAttribute(LOGO_ATTRIBUTE_NAME);
    }

    /**
     * 获取描述
     *
     * @return 描述
     */
    public String getDescription() {
        PluginConfig pluginConfig = getConfig();
        return pluginConfig == null ? null : pluginConfig.getAttribute(DESCRIPTION_ATTRIBUTE_NAME);
    }

    /**
     * 获取支付前处理URL
     *
     * @param paymentSn 支付编号
     * @param extra     附加内容
     * @return 支付前处理URL
     */
    public String getPayBeforeUrl(String paymentSn, String extra) {
        String url = systemProperties.getWebsite() + "/payment/before/" + paymentSn;
        return extra == null || extra.isEmpty() ? url : url + "/" + extra;
    }

    /**
     * 获取支付处理URL
     *
     * @param paymentSn 支付编号
     * @param extra     附加内容
     * @return 支付处理URL
     */
    public String getPayUrl(String paymentSn, String extra) {
        String url = systemProperties.getWebsite() + "/payment/pay/" + paymentSn;
        return extra == null || extra.isEmpty() ? url : url + "/" + extra;
    }

    /**
     * 获取支付后处理URL
     *
     * @param paymentSn 支付编号
     * @param extra     附加内容
     * @return 支付后处理URL
     */
    public String getPayAfterUrl(String paymentSn, String extra) {
        String url = systemProperties.getWebsite() + "/payment/after/" + paymentSn;
        return extra == null || extra.isEmpty() ? url : url + "/" + extra;
    }

    /**
     * 支付前处理
     *
     * @param paymentTransaction 支付事物
     * @param paymentDescription 支付描述
     * @param extra              附加内容
     * @param request            HttpServletRequest
     * @param response           HttpServletResponse
     * @return 返回支付页面
     */
    public String payBeforeHandle(PaymentTransaction paymentTransaction, String paymentDescription, String extra, HttpServletRequest request, HttpServletResponse response) {
        return "redirect:" + getPayUrl(paymentTransaction.getSn(), extra);
    }

    /**
     * 支付处理
     *
     * @param paymentTransaction 支付事物
     * @param paymentDescription 支付描述
     * @param extra              附加内容
     * @param request            HttpServletRequest
     * @param response           HttpServletResponse
     * @return 返回支付后页面
     */
    public String payHandle(PaymentTransaction paymentTransaction, String paymentDescription, String extra, HttpServletRequest request, HttpServletResponse response) {
        request.setAttribute("title", getDisplayName());
        return DEFAULT_PAY_VIEW_NAME;
    }

    /**
     * 支付后处理
     *
     * @param paymentTransaction 支付事物
     * @param paymentDescription 支付描述
     * @param extra              附加内容
     * @param isPaySuccess       是否支付成功
     * @param request            HttpServletRequest
     * @param response           HttpServletResponse
     * @return 返回支付结果页面
     */
    public String payAfterHandle(PaymentTransaction paymentTransaction, String paymentDescription, String extra, boolean isPaySuccess, HttpServletRequest request, HttpServletResponse response) {
        return DEFAULT_PAY_RESULT_VIEW_NAME;
    }

    /**
     * 判断是否支付成功
     *
     * @param paymentTransaction 支付事物
     * @param paymentDescription 支付描述
     * @param extra              附加内容
     * @param request            HttpServletRequest
     * @param response           HttpServletResponse
     * @return 是否支付成功
     */
    public abstract boolean isPaySuccess(PaymentTransaction paymentTransaction, String paymentDescription, String extra, HttpServletRequest request, HttpServletResponse response);

    /**
     * 获取超时时间
     *
     * @return 超时时间
     */
    public Integer getTimeout() {
        return PaymentPlugin.DEFAULT_TIMEOUT;
    }

    /**
     * 计算支付手续费
     *
     * @param amount 金额
     * @return 支付手续费
     */
    public BigDecimal calculateFee(BigDecimal amount) {
        return BigDecimal.ZERO;
    }

    /**
     * 计算支付金额
     *
     * @param amount 金额
     * @return 支付金额
     */
    public BigDecimal calculateAmount(BigDecimal amount) {
        return amount.add(calculateFee(amount)).setScale(2, RoundingMode.UP);
    }
}